﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024-2025 LiLong                                              **
**  This file is part of OpenVisaApplication.                                   **
**                                                                              **
**  OpenVisaApplication is free software: you can redistribute it and/or modify **
**  it under the terms of the GNU General Public License as published by        **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  OpenVisaApplication is distributed in the hope that it will be useful,      **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU General Public License for more details.                                **
**                                                                              **
**  You should have received a copy of the GNU General Public License           **
**  along with OpenVisaApplication. If not, see <https://www.gnu.org/licenses/>.**
**********************************************************************************/
#pragma once

#include "DeviceItem.h"
#include "DeviceType.h"

#include <OpenVisa/Object.h>

namespace AppCore
{
class Device : public DeviceItem
{
public:
    inline Device() : m_object(std::make_shared<OpenVisa::Object>()) {}
    inline ~Device() {};
    inline std::shared_ptr<OpenVisa::Object> object() const { return m_object; }

private:
    std::shared_ptr<OpenVisa::Object> m_object;
};

class SerialPortDevice
    : public Device
    , public _DeviceTypeHelper<DeviceType::Type::SerialPort>
{
public:
    enum class Parity
    {
        None,
        Odd,
        Even
    };
    enum class FlowControl
    {
        None,
        Software,
        Hardware
    };
    enum class StopBits
    {
        One,
        OnePointFive,
        Two
    };
    inline SerialPortDevice(const QString& portName) : m_portName(portName) { setName(m_portName); }
    const QString& portName() const { return m_portName; }
    inline void setBuadrate(unsigned buadrate) { m_buadrate = buadrate; }
    inline unsigned buadrate() const { return m_buadrate; }
    inline void setDataBits(unsigned char bits) { m_dataBits = bits; }
    inline unsigned char dataBits() const { return m_dataBits; }
    inline void setParity(Parity p) { m_parity = p; }
    inline Parity parity() const { return m_parity; }
    inline void setFlowControl(FlowControl fc) { m_flowControl = fc; }
    inline FlowControl flowControl() const { return m_flowControl; }
    inline void setStopBits(StopBits sb) { m_stopBits = sb; }
    inline StopBits stopBits() const { return m_stopBits; }

private:
    QString m_portName;
    unsigned m_buadrate { 9600 };
    unsigned char m_dataBits { 8 };
    Parity m_parity { Parity::None };
    FlowControl m_flowControl { FlowControl::None };
    StopBits m_stopBits { StopBits::One };
};

class UsbTmcDevice
    : public Device
    , public _DeviceTypeHelper<DeviceType::Type::USB>
{
public:
    inline UsbTmcDevice(unsigned short vid, unsigned short pid, const QString& sn) : m_vid(vid), m_pid(pid), m_serialNumber(sn)
    {
        setName(QString("USB::0x%1::0x%2::%3").arg(m_vid, 4, 16, QChar('0')).arg(m_pid, 4, 16, QChar('0')).arg(sn));
    }
    inline unsigned short vendorId() const { return m_vid; }
    inline unsigned short productId() const { return m_pid; }
    inline const QString& serialNumber() const { return m_serialNumber; }

private:
    unsigned short m_vid;
    unsigned short m_pid;
    QString m_serialNumber;
};

class NetworkDevice
    : public Device
    , public _DeviceTypeHelper<DeviceType::Type::Network>
{
public:
    inline NetworkDevice(const QString& address)
    {
        setAddress(address);
        setName(address);
    }
};
} // namespace AppCore